#include "enpctrl.h"
#include "CTKeyValue.h"

bool CEnpCtrl::s_bReloadConfig = false;
bool CEnpCtrl::s_bExit = false;

CEnpCtrl::CEnpCtrl()
{
	m_uiNow = static_cast<unsigned int>(time(0));

    // 统计项描述
    const char g_aszEnpStatDesc[][CTStatItem::CTLIB_DESC_MAX] =
    {
        "RecvMessage",
        "SendMessage",
        "Accept",
        "IdleClose",
        "MainLoop",
        "WaitTimeout",
        "Check"
    };

    m_stat.Init(CT_COUNTOF(g_aszEnpStatDesc), g_aszEnpStatDesc);
}

void CEnpCtrl::sigusr1_handle(int CT_UNUSED(iSigVal))
{
    s_bReloadConfig = true;
    signal(SIGUSR1, CEnpCtrl::sigusr1_handle);
}

void CEnpCtrl::sigusr2_handle(int CT_UNUSED(iSigVal))
{
    s_bExit = true;
    signal(SIGUSR2, CEnpCtrl::sigusr2_handle);
}

int CEnpCtrl::Init()
{
    int iRet = 0;

    // 安装信号处理函数
    signal(SIGUSR1, CEnpCtrl::sigusr1_handle); // kill -USR1 pid 会让程序重读配置
    signal(SIGUSR2, CEnpCtrl::sigusr2_handle); // kill -USR2 pid 会让程序安全退出

	// 读取配置
	CONF->LoadConfig();

    // 创建Epoll
    iRet = m_stEpoll.Init(CONF->SocketMaxCount, ENP_WAIT_SIZE);
    CHECK_THROW(iRet);

    // 创建共享内存队列
    m_astShmQueue.m_iUsedCount = m_astShmQueue.GetCount();
    for (int i = 0; i < m_astShmQueue.Size(); ++i)
    {
        CT_INFO(("Init EnpShm Key = %s",CONF->FrontEndShmKeyArray[i].Get()));
        iRet = m_astShmQueue[i].Init(false,
            CONF->FrontEndShmKeyArray[i].Get(), CONF->FrontEndShmSize,
            CONF->FrontEndSocketArray[i].Get(),
            CONF->BackEndSocketArray[i].Get(),
            m_stEpoll,
            *this,
            &CEnpCtrl::OnShmQueueEvent, i);
        CHECK_THROW(iRet);
    }

	// 创建共享内存
	const size_t iClientSize = m_stClientFactory.CountSize(CONF->SocketMaxCount);
	const size_t iRecvBufSize = m_stRecvBufMgr.CountSize(CONF->BufferCount, CONF->RecvBufferSize);
    const size_t iSendBufSize = m_stSendBufMgr.CountSize(CONF->BufferCount, CONF->SendBufferSize);
    const size_t iShmSize = iClientSize + iRecvBufSize + iSendBufSize;
    iRet = m_stHandleMgrShm.Create(CONF->MgrShmKey(), iShmSize);
    CHECK_RETURN(iRet);
    memset(m_stHandleMgrShm.GetBuffer(), 0, m_stHandleMgrShm.GetSize());
    CT_INFO(("create buffer shm's shm at %p ok. key=%s size=%d clientsize=%d recvbufsize=%d sendbufsize=%d",
        m_stHandleMgrShm.GetBuffer(), CONF->MgrShmKey(), iShmSize, iClientSize, iRecvBufSize, iSendBufSize));

    // 初始化工厂
	iRet = m_stClientFactory.Init(m_stHandleMgrShm.GetBuffer(),
        iClientSize, CONF->SocketMaxCount);
    CHECK_RETURN(iRet);

    CT_INFO(("ENP init: initialing buffer"));
    // 初始化接收缓冲区
    iRet = m_stRecvBufMgr.Init(m_stHandleMgrShm.GetBuffer() + iClientSize,
        CONF->BufferCount, CONF->RecvBufferSize);
    CHECK_RETURN(iRet);

    // 初始化发送缓冲区
    iRet = m_stSendBufMgr.Init(m_stHandleMgrShm.GetBuffer() + iClientSize + iRecvBufSize,
        CONF->BufferCount, CONF->SendBufferSize);
    CHECK_RETURN(iRet);

    // 侦听端口
    CT_INFO(("ENP init: start listenning"));
    m_astListen.m_iUsedCount = CONF->ListenArray.m_iUsedCount;
	for (int i = 0; i < CONF->ListenArray.m_iUsedCount; ++i)
	{
        iRet = m_astListen[i].Init(*this, CONF->ListenArray[i]);
        CHECK_THROW(iRet);
	}

    // 临时缓冲区
    iRet = m_stTempBuf.Attach(NULL, CONF->SendBufferSize + sizeof(CEnpNetHead), 0);
    CHECK_RETURN(iRet);

    // 流量控制对象初始化
    m_stFlowCtrl.Init(CONF->MaxConnect, CONF->NewConnCheckInterval, CONF->NewConnMax,
                        CONF->SendUpCheckInterval, CONF->SendUpMax, CONF->StopAccecptInterval);

	CT_INFO(("ENP init ok"));

	return 0;
}

int CEnpCtrl::Run()
{
    int iRet = 0;
    int iLoop = 0;

    m_uiNow = static_cast<unsigned int>(time(0));
    int iPrevNow = m_uiNow;
    while (true)
    {
        // 信号检查
        if (s_bReloadConfig)
        {
            s_bReloadConfig = false;
            CONF->ReloadConfig();
        }

        if (s_bExit)
        {
            //SendRemainData();
            s_bExit = false;
            return 0;
        }

	    m_stat.Put(enp_stat_mainloop);

	    // 定时器检查
	    if (iLoop == 0)
	    {
 		    m_uiNow = (unsigned int) time(0);
		    if (m_uiNow - iPrevNow >= 60)
		    {
			    iPrevNow = m_uiNow;
			    DumpStatInfo();
		    }
	    }

        iRet = m_stEpoll.WaitAndEvent(10);
        if (iRet == 0) // 超时了
        {
            m_stat.Put(enp_stat_waittimeout);
        }

        // 从发送队列中取消息并处理
        for (int i = 0; i < CONF->ZoneKeyArray.Size(); ++i)
        {
            HandleShmQueueMsg(i);
        }

        // 遗留未发送的数据的检查
	    if (++iLoop >= 50)
	    {
		    iLoop = 0;
		    m_stat.Put(enp_stat_check);
		    CheckIdle();
            CheckRemain();  //@@ 可以改用定时器实现
	    }
    }

    return 0;
}

int CEnpCtrl::Exit()
{
    CT_INFO(("%s exit", APPNAME));
    return 0;
}

void CEnpCtrl::OnShmQueueEvent(CEnpEpollObject* pstObject, SOCKET iSocket, int iEvent)
{
    CT_TRACE(("OnShmQueueEvent socket=%d event=%d", iSocket, iEvent));
    m_astShmQueue[pstObject->GetActID()].ClearNotify(); // 接收Notify数据, 否则会一直收到事件

    if (!CTEpoll::IsInputEvent(iEvent))
    {
        CT_WARNING(("ShmQueue recv not match event(%d) socket=%d", iEvent, iSocket));
        return;
    }

    HandleShmQueueMsg(pstObject->GetActID());
}

void CEnpCtrl::HandleShmQueueMsg(int iShmQueueIndex)
{
    // 分配发送缓冲区;
    // 发送数据;
    // 如果发送缓冲区为空就释放;

    int iRet = 0;
    for (;;)
    {
        if (!m_astShmQueue[iShmQueueIndex].HasCode())
        {
            return;
        }

        // 接收消息
        int iCodeLen = 0;
        m_stTempBuf.Clear();
        iRet = m_astShmQueue[iShmQueueIndex].GetOneCode(m_stTempBuf.GetFreeBuf(), m_stTempBuf.GetFreeLen(), iCodeLen);
        if (iRet || iCodeLen < (int)sizeof(CEnpNetHead))
        {
            CT_WARNING(("get code from shmqueue failed ret=%d, codelen=%d", iRet, iCodeLen));
            continue;
        }
        m_stTempBuf.Append(iCodeLen);

        // 先获取NetHead
        CEnpNetHead& stHead = *(CEnpNetHead*)m_stTempBuf.GetUsedBuf();
        if (iCodeLen != (int)sizeof(CEnpNetHead) + stHead.unDataLength) // 长度不一致
        {
            CT_WARNING(("code length invalid. %d != %d + %d", iCodeLen,
                sizeof(CEnpNetHead), stHead.unDataLength));
            continue;
        }

        // 寻找对应的Client
        int iIndex = stHead.uiHandle;
        CEnpClient* pstClient = m_stClientFactory.CalcObject(iIndex);
        if (!pstClient)
        {
            CT_WARNING(("nethead not match client: handle=%u", iIndex));
            continue;
        }

		if (m_stClientFactory.IsFree(pstClient))
		{
			CT_WARNING(("client(%d) has been freed, maybe client disconnected", iIndex));
            PutOneNotify(stHead, enp_flag_remoteclose, iShmQueueIndex);     //告诉上层不要再下发这个连接相关的消息了
			continue;
		}

        // 检查数据长度是否合法
        if ((int)stHead.unDataLength > CONF->SendBufferSize)
        {
            CT_WARNING(("nethead(%d) datalen(%d > %d) invalid", iIndex,
                stHead.unDataLength, CONF->SendBufferSize));
            continue;
        }

		/*
        // 检查seq是否匹配
        if (pstClient->m_stNetHead.uiHandleSeq != pstClient->m_uiSeq)
        {
            CT_WARNING(("client seq(%d) != nethead seq(%d))",
                pstClient->m_uiSeq, pstClient->m_stNetHead.uiHandleSeq));
            continue;
        }
		*/

        // 检查IP和端口是否匹配
        if (pstClient->m_stNetHead.uiRemoteIP != stHead.uiRemoteIP ||
            pstClient->m_stNetHead.unRemotePort != stHead.unRemotePort ||
            stHead.uiRemoteIP == 0 ||
            stHead.unRemotePort == 0)
        {
            CT_WARNING(("nethead(%d) ip invalid (%d:%d != %d:%d || %d:%d == 0)",
                iIndex,
                pstClient->m_stNetHead.uiRemoteIP, pstClient->m_stNetHead.unRemotePort,
                stHead.uiRemoteIP, stHead.unRemotePort,
                stHead.uiRemoteIP, stHead.unRemotePort));
            continue;
        }

        // 获取上层的flag, 只有当高8位不为0时才设置
        if (stHead.unLiveFlag & 0xFF00)
        {
            pstClient->m_stNetHead.unLiveFlag = stHead.unLiveFlag & 0xFF00;
        }

        // 检查上层状态
        if (pstClient->m_stNetHead.unLiveFlag & enp_flag_busy)  // 上层出现繁忙
        {
            m_stFlowCtrl.StopAccecpt();
        }

        pstClient->m_stNetHead.uiAct1 = stHead.uiAct1;
        pstClient->m_stNetHead.uiAct2 = stHead.uiAct2;
        memcpy(pstClient->m_stNetHead.szPtKey, stHead.szPtKey, sizeof(pstClient->m_stNetHead.szPtKey));

        CT_TRACE(("get msg from shmqueue. handle=%d datalen=%d seq=%u",
			iIndex, stHead.unDataLength, stHead.uiHandleSeq));
        DumpNetHead(stHead);
        DumpHandleInfo(pstClient);

        iRet = AllocSendBuffer(pstClient);
        if (iRet)
        {
            CT_FATAL(("AllocSendBuffer failed %d", iRet));
            return;
        }

        if (stHead.unDataLength > 0)
        {
			if (pstClient->m_pstListern->m_stListenInfo.m_ucEncodeMethod == CODE_PROTOBUF ||
				pstClient->m_pstListern->m_stListenInfo.m_ucEncodeMethod == CODE_BIN ||
				pstClient->m_pstListern->m_stListenInfo.m_ucEncodeMethod == CODE_JSON)
            {
                int iNeedSendBufLen = (int)(sizeof(int) + stHead.unDataLength);
                if (pstClient->m_pstListern->m_stListenInfo.m_ucEncodeMethod == CODE_PROTOBUF)
                {
                    iNeedSendBufLen += sizeof(char);
                }

                if (pstClient->m_stSendBuf.GetFreeLen() < iNeedSendBufLen)
                {
                    CT_WARNING(("send buff is not enough"));
                    continue;
                }
                //增加四个字节的长度
                int iLen = htonl((int)(stHead.unDataLength + sizeof(int)));
				if (pstClient->m_pstListern->m_stListenInfo.m_ucEncodeMethod == CODE_PROTOBUF)
				{
                	iLen = htonl((int)(stHead.unDataLength + sizeof(int) + sizeof(char)));
				}
                pstClient->m_stSendBuf.Append((char*)&iLen, sizeof(int));
            }

            iRet = pstClient->m_stSendBuf.Append(m_stTempBuf.GetUsedBuf() + sizeof(CEnpNetHead),
                stHead.unDataLength);

            if (iRet == 0 && pstClient->m_pstListern->m_stListenInfo.m_ucEncodeMethod == CODE_PROTOBUF)
            {
                iRet = pstClient->m_stSendBuf.Append("\t", 1);
            }
			else if (iRet == 0 && pstClient->m_pstListern->m_stListenInfo.m_ucEncodeMethod == CODE_STRING)
            {
                iRet = pstClient->m_stSendBuf.Append("\n", 1);
            }

            if (iRet)
            {
                if (pstClient->m_stSendBuf.GetUsedLen() == 0)
                {
                    FreeSendBuffer(pstClient);
                }

                CT_WARNING(("append data failed, ret=%d, datalen=%d, freelen=%d",
                    iRet, stHead.unDataLength, m_stTempBuf.GetFreeLen()));
                continue;
            }

            CT_TRACE(("handle(%d) has %d bytes to send", iIndex,
                pstClient->m_stSendBuf.GetUsedLen()));
        }

        if (pstClient->m_stSendBuf.GetUsedLen() == 0)
        {
            CT_TRACE(("no data to send"));
            FreeSendBuffer(pstClient);
            continue;
        }

        CT_TRACE(("---- handle(%d) begin send data, len=%d ---", iIndex,
            pstClient->m_stSendBuf.GetUsedLen()));

        m_stat.Put(enp_stat_sendmsg);

        // 发送数据
        iRet = SendSocket(pstClient);
        if (iRet)
        {
            CT_ERROR(("send data failed %d", iRet));
            continue;
        }
    }
}

void CEnpCtrl::OnListenEvent(CEnpEpollObject* pstObject, SOCKET iSocket, int iEvent)
{
    CT_TRACE(("recv listen event, event = %d", iEvent));
    if (!CTEpoll::IsInputEvent(iEvent))
    {
        CT_WARNING(("listen socket recv not match event(%d) socket=%d", iEvent, iSocket));
        return;
    }

    int iRet = 0;
    CEnpListen* pstListen = (CEnpListen*) pstObject;
    pstListen->m_uiLastTime = m_uiNow;
    m_stat.Put(enp_stat_accept);

    /*必须先accept才能做流控检查，不然连接很久不会释放 by will
    //过载检查
    if (m_stFlowCtrl.IsOverflow())
    {
        CT_WARNING(("over flow: %s", m_stFlowCtrl.GetStat()));
        return;
    }
    */

    // 接受连接
    struct sockaddr_in clientaddr;
    socklen_t clilen = sizeof(clientaddr);
    SOCKET s = INVALID_SOCKET;
    iRet = pstListen->m_stSocket.Accept(s, (sockaddr *)&clientaddr, &clilen);
    if (iRet)
    {
        // 客户端连接上来以后又立即关闭了
        CT_WARNING(("remote connect and close. listen=%d ret=%d errno=%d",
            iSocket, iRet, CT_WSA_ERRNO));
        return;
    }

    //必须先accept才能做流控检查，不然连接很久不会释放 by will
    //过载检查
    if (m_stFlowCtrl.IsOverflow())
    {
        CT_WARNING(("over flow: %s", m_stFlowCtrl.GetStat()));
        closesocket(s);
        s = INVALID_SOCKET;
        return;
    }

    // 记录新连接
    m_stFlowCtrl.AcceptConnect();

    // 从工厂分配CEnpClient
    CEnpClient* pstClient = m_stClientFactory.Alloc();
    if (!pstClient)
    {
        CT_WARNING(("m_stClientFactory.Alloc failed"));
        //CloseSocket(pstClient, enp_flag_error);
        return;
    }

    iRet = pstClient->Init(*this, *pstListen, s,
        clientaddr.sin_addr.s_addr, ntohs(clientaddr.sin_port));
	pstClient->m_uiSeq = m_stClientFactory.GetClientSeq();
    CHECK_THROW(iRet);

    CT_TRACE(("Client %s:%d connected port %d at sock %d",
        inet_ntoa(clientaddr.sin_addr),
        ntohs(clientaddr.sin_port),
        pstListen->m_stListenInfo.m_unListenPort,
        s));
}

void CEnpCtrl::OnClientEvent(CEnpEpollObject* pstObject, SOCKET iSocket, int iEvent)
{
    CEnpClient* pstClient = (CEnpClient*) pstObject;
    CT_TRACE(("client socket %d handle %d event=%d",
        iSocket, pstClient->m_stNetHead.uiHandle, iEvent));

    if (CTEpoll::IsCloseEvent(iEvent))
    {
        CloseSocket(pstClient, enp_flag_remoteclose);
    }

    if (CTEpoll::IsInputEvent(iEvent))
    {
        // 分配接收缓冲区;
        // 接收数据;
        // 如果是完整的包就放入CTShmQueue;
        // 如果接收缓冲区为空就释放;
        RecvSocket(pstClient);
    }

    if (CTEpoll::IsOutputEvent(iEvent))
    {
        CT_WARNING(("client socket recv not match event(%d) socket=%d", iEvent, iSocket));
        return;
    }
}

int CEnpCtrl::CheckIdle()
{
	int iIndex, iNewIdx;
	for (iIndex = m_stClientFactory.Head(USED_LIST, ALLOC_INDEX);
         iIndex >= 0;
         iIndex = iNewIdx)
	{
		iNewIdx = m_stClientFactory.Next(iIndex, ALLOC_INDEX);
        CEnpClient* pstClient = m_stClientFactory.CalcObject(iIndex);
        CT_ASSERT(pstClient);

		if (!pstClient->m_stSocket.IsValid())
		{
			CT_WARNING(("CheckIdle handle(%d) socket invalid", iIndex));
			continue;
		}

		if ((m_uiNow - pstClient->m_stNetHead.uiLastTime) >
                pstClient->m_pstListern->m_stListenInfo.m_uiIdleTimeout)
		{
			m_stat.Put(enp_stat_idleclose);
			CT_TRACE(("CheckIdle handle(%d) socket(%d) close",
                iIndex, pstClient->m_stSocket.GetSocket()));
			DumpHandleInfo(pstClient);
			CloseSocket(pstClient, enp_flag_idleclose);
		}
	}

    return 0;
}

int CEnpCtrl::CheckRemain()
{
    int iIndex, iNewIdx;
    for (iIndex = m_stClientFactory.Head(REMAIN_LIST, REMAIN_INDEX);
        iIndex >= 0;
        iIndex = iNewIdx)
    {
        iNewIdx = m_stClientFactory.Next(iIndex, REMAIN_INDEX);
        CEnpClient* pstClient = m_stClientFactory.CalcObject(iIndex);
        CT_ASSERT(pstClient);

        if (pstClient->m_stSendBuf.GetUsedLen() > 0)
        {
            SendSocket(pstClient);
        }
    }

    return 0;
}

int CEnpCtrl::AfterRecvSocket(CEnpClient* pstClient)
{
	// 判断Buf中是否有消息可以放到接收队列中
	int iLen = 0;
	int iRet = 0;
    char* szMsgBuf = NULL;
    int iMsgLen = 0;

	while (true)
	{
        iRet = 0;
        iMsgLen = 0;
        szMsgBuf = NULL;
        iLen = 0;

		if (pstClient->m_stRecvBuf.GetUsedLen() == 0)
		{
			CT_TRACE(("recvbuf len = 0, PutOneMessage over"));
			break;
		}

        iRet = BufferHasMessage(pstClient, iLen, szMsgBuf, iMsgLen);
		if (iRet || iMsgLen == 0 || szMsgBuf == NULL)
		{
            if (iRet == 0 && iMsgLen != 0 && iMsgLen > pstClient->m_stRecvBuf.GetBufferSize())
            {
                CT_WARNING(("recv a msg len great than recv buff, msglen = %d, bufmax = %d",
					iMsgLen, pstClient->m_stRecvBuf.GetBufferSize()));
                CloseSocket(pstClient, enp_flag_msg_too_big);
                return 0;
            }
            else if (-2 == iRet)
            {//The received package is corrupted, just force close this client connection.
                CT_WARNING(("BufferHasMessage returns %d, close this client instance", iRet));
                CloseSocket(pstClient, enp_flag_error);
                return 0;
            }
			CT_TRACE(("no msg in buf, ret = %d, msglen = %d, buf = %p", iRet, iMsgLen, szMsgBuf));
			break;
		}

        if (IsPolicyString(pstClient))
        {
            CheckPolicyString(pstClient);
            break;
        }

		CT_TRACE(("Has one message len=%d msglen=%d, put to RecvQueue", iLen, iMsgLen));
        m_stat.Put(enp_stat_recvmsg);
        iRet = PutOneMessage(pstClient, iLen, szMsgBuf, iMsgLen);
		if (iRet)
		{
			CT_ERROR(("PutOneMessage failed %d", iRet));
			break;
		}
	}

    // 用完的就释放
	if (pstClient->m_stRecvBuf.GetUsedLen() == 0)
	{
		FreeRecvBuffer(pstClient);
	}

	return iRet;
}

int CEnpCtrl::AfterSendSocket(CEnpClient* pstClient)
{
	CT_TRACE(("---- handle(%d) data send finished. left %d bytes ----",
        m_stClientFactory.CalcObjectPos(pstClient),
        pstClient->m_stSendBuf.GetUsedLen()));

	if (pstClient->m_stSendBuf.GetUsedLen() == 0) // no more data to send
	{
		if (pstClient->m_stNetHead.unLiveFlag & enp_flag_askclose) // app ask to close handle
		{
			return CloseSocket(pstClient, enp_flag_askclose);
		}
		else // 释放
		{
            m_stClientFactory.SetEmpty(pstClient);
			return FreeSendBuffer(pstClient);
		}
	}
	else
	{
        // 有残留数据, 放到残留数据队列
        return m_stClientFactory.SetRemain(pstClient);
	}
}

int CEnpCtrl::PutOneMessage(CEnpClient* pstClient, int iLen, const char* szMsgBuf, int iMsgLen)
{
	int iRet = 0;

	CT_TRACE(("TGW:Client(%u) Put Msg(len=%d) To ShmQueue(%d)", pstClient->m_uiSeq, iMsgLen, pstClient->m_iShmQueueIndex));

    // 先放入消息头
	pstClient->m_stNetHead.uiHandleSeq = pstClient->m_uiSeq;
    pstClient->m_stNetHead.unDataLength = static_cast<unsigned short>(iMsgLen);
    iRet = m_astShmQueue[pstClient->m_iShmQueueIndex].PutOneCode(
        (const char*)(&pstClient->m_stNetHead), sizeof(pstClient->m_stNetHead),
        szMsgBuf, iMsgLen);
    if (iRet)
    {
        return -3;
    }

    pstClient->m_iRecvBytes += iLen;
    pstClient->m_stRecvBuf.Remove(iLen);

    // 记录发送数据包
    m_stFlowCtrl.SendOneMsgUp();

    return 0;
}

int CEnpCtrl::PutOneNotify(CEnpClient* pstClient, unsigned short unLiveFlag)
{
	return PutOneNotify(pstClient->m_stNetHead, unLiveFlag, pstClient->m_iShmQueueIndex);
}

int CEnpCtrl::PutOneNotify(CEnpNetHead& stNetHead, unsigned short unLiveFlag, int iShmQueueIndex)
{
    int iRet = 0;

    CT_TRACE(("PutOneNotify flag=%d", unLiveFlag));
    stNetHead.unLiveFlag = unLiveFlag;
    stNetHead.unDataLength = 0;

    iRet = m_astShmQueue[iShmQueueIndex].PutOneCode((char*)(&stNetHead), sizeof(stNetHead));
    if (iRet)
    {
        CT_ERROR(("PutOneNotify failed %d", iRet));
    }

    return iRet;
}

int CEnpCtrl::BufferHasMessage(CEnpClient* pstClient, int& iLen, char*& pszMsgBuf, int& iMsgLen)
{
	iLen = 0;
    pszMsgBuf = NULL;
    iMsgLen = 0;

    if (pstClient->m_pstListern->m_stListenInfo.m_stPackageType == enp_package_http)
    {
        //http协议一次只允许发一个包, 不允许粘包

        if (pstClient->m_stRecvBuf.GetFreeLen() <= 0) //不允许发满
        {
            return -2;
        }

        pstClient->m_stRecvBuf.GetUsedBuf()[pstClient->m_stRecvBuf.GetUsedLen()] = '\0'; //为了安全的strstr

        int iQueueIndex = -1;

        const char* pEndTmp = strstr(pstClient->m_stRecvBuf.GetUsedBuf(), "\r\n");
        if (pEndTmp)
        {
            CTKeyValue stKeyVal;
            stKeyVal.ParseFromHttpParam(pstClient->m_stRecvBuf.GetUsedBuf(), (int)(pEndTmp - pstClient->m_stRecvBuf.GetUsedBuf()));

            int iZoneID = CTStringUtils::StrToInt<int>(stKeyVal.GetValue("zoneid"));
            int iServerID = CTStringUtils::StrToInt<int>(stKeyVal.GetValue("serverid"));
            int iServerIDTwo = CTStringUtils::StrToInt<int>(stKeyVal.GetValue("serverId"));
            if (iZoneID > 0)
            {
                iQueueIndex = CONF->GetIndexByZoneID(iZoneID);
                if (iQueueIndex >= 0)
                {
                    pstClient->SetShmQueueIndex(iQueueIndex);
                    CT_TRACE(("TGW:Client(%u) Chg Shm Queue Index(%d)", pstClient->m_uiSeq, iQueueIndex));
                }
            }
            if (iQueueIndex < 0 && iServerID > 0)
            {
                iQueueIndex = CONF->GetIndexByWebID(iServerID);
                if (iQueueIndex >= 0)
                {
                    pstClient->SetShmQueueIndex(iQueueIndex);
                    CT_TRACE(("TGW:Client(%u) Chg Shm Queue Index(%d)", pstClient->m_uiSeq, iQueueIndex));
                }
            }
            if (iQueueIndex < 0 && iServerIDTwo > 0)
            {
                iQueueIndex = CONF->GetIndexByWebID(iServerIDTwo);
                if (iQueueIndex >= 0)
                {
                    pstClient->SetShmQueueIndex(iQueueIndex);
                    CT_TRACE(("TGW:Client(%u) Chg Shm Queue Index(%d)", pstClient->m_uiSeq, iQueueIndex));
                }
            }
        }

        const char* pEnd = strstr(pstClient->m_stRecvBuf.GetUsedBuf(), "\r\n\r\n");
        if (pEnd)
        {
            pstClient->m_stRecvBuf.Append("\0", 1); //为了能安全
            iLen = (int) (pEnd - pstClient->m_stRecvBuf.GetUsedBuf()) + 5; 
            if (iLen != pstClient->m_stRecvBuf.GetUsedLen())
            {
                iMsgLen = 0;
                CT_ERROR(("invalid http req %s", pstClient->m_stRecvBuf.GetUsedBuf()));
                return -2;
            }

            pszMsgBuf = pstClient->m_stRecvBuf.GetUsedBuf();
            iMsgLen = iLen;

            //处理http类型消息
            const char* pQue = strchr(pszMsgBuf, '?');
            if (pQue && pEnd - pQue > 0)
            {
                ++pQue; //去掉?
                CTKeyValue stKeyVal;
                stKeyVal.ParseFromHttpParam(pQue, pEnd - pQue);
                int iZoneID = CTStringUtils::StrToInt<int>(stKeyVal.GetValue("zoneid"));
                int iServerID = CTStringUtils::StrToInt<int>(stKeyVal.GetValue("serverid"));
                int iServerIDTwo = CTStringUtils::StrToInt<int>(stKeyVal.GetValue("serverId"));
                if (iQueueIndex < 0 && iZoneID > 0)
                {
                    iQueueIndex = CONF->GetIndexByZoneID(iZoneID);
                    if (iQueueIndex >= 0)
                    {
                        pstClient->SetShmQueueIndex(iQueueIndex);
                        CT_TRACE(("TGW:Client(%u) Chg Shm Queue Index(%d)", pstClient->m_uiSeq, iQueueIndex));
                    }
                }
                if (iQueueIndex < 0 && iServerID > 0)
                {
                    iQueueIndex = CONF->GetIndexByWebID(iServerID);
                    if (iQueueIndex >= 0)
                    {
                        pstClient->SetShmQueueIndex(iQueueIndex);
                        CT_TRACE(("TGW:Client(%u) Chg Shm Queue Index(%d)", pstClient->m_uiSeq, iQueueIndex));
                    }
                }
                if (iQueueIndex < 0 && iServerIDTwo > 0)
                {
                    iQueueIndex = CONF->GetIndexByWebID(iServerIDTwo);
                    if (iQueueIndex >= 0)
                    {
                        pstClient->SetShmQueueIndex(iQueueIndex);
                        CT_TRACE(("TGW:Client(%u) Chg Shm Queue Index(%d)", pstClient->m_uiSeq, iQueueIndex));
                    }
                }
            }
        }

        if (iQueueIndex < 0)
        {
            CT_ERROR(("TGW:Client(%u) %s", pstClient->m_uiSeq, pstClient->m_stRecvBuf.GetUsedBuf()));
        }

        return 0;
    }
    else if (pstClient->m_pstListern->m_stListenInfo.m_stPackageType == enp_package_protobuf)
	{
        if (pstClient->m_stRecvBuf.GetUsedLen() < (int)sizeof(int))
        {
            iMsgLen = 0;
            return 0;
        }

        if (IsPolicyString(pstClient))
        {
            iMsgLen = FLASH_POLICY_STRING_LEN + 1;
            iLen = FLASH_POLICY_STRING_LEN + 1;
            pszMsgBuf = pstClient->m_stRecvBuf.GetUsedBuf();
            return 0;
        }

        if (FromAdmin(pstClient->m_stNetHead))
        {
            int iQueueIndex = -1;
            const char* pFlag = strchr(pstClient->m_stRecvBuf.GetUsedBuf(), '|');
            
            if (NULL != pFlag && pFlag - pstClient->m_stRecvBuf.GetUsedBuf() > 0)
            {
                CTKeyValue stKeyVal;
                stKeyVal.ParseFromHttpParam(pstClient->m_stRecvBuf.GetUsedBuf(), pFlag - pstClient->m_stRecvBuf.GetUsedBuf());
                int iZoneID = CTStringUtils::StrToInt<int>(stKeyVal.GetValue("zoneid"));
                if (iZoneID > 0)
                {
                    iQueueIndex = CONF->GetIndexByZoneID(iZoneID);
                    if (iQueueIndex >= 0)
                    {
                        pstClient->SetShmQueueIndex(iQueueIndex);
                        CT_TRACE(("TGW:Client(%u) Chg Shm Queue Index(%d)", pstClient->m_uiSeq, iQueueIndex));
                    }
                }
            }

            if (iQueueIndex < 0)
            {
                CT_ERROR(("TGW:Client(%u) %s", pstClient->m_uiSeq, pstClient->m_stRecvBuf.GetUsedBuf()));
                return -2;
            }
            else
            {
                pstClient->m_stRecvBuf.Remove(pFlag + 1 - pstClient->m_stRecvBuf.GetUsedBuf());
            }
        }

        //腾讯平台TWG包头需丢弃
        if (strncmp(pstClient->m_stRecvBuf.GetUsedBuf(), "tgw", 3) == 0)
        {
            pstClient->m_stRecvBuf.GetUsedBuf()[pstClient->m_stRecvBuf.GetUsedLen()] = '\0'; //为了安全的strstr

            char * p = strstr(pstClient->m_stRecvBuf.GetUsedBuf(), "\r\n\r\n");
            if (p != NULL)
            {
                pstClient->m_stRecvBuf.Remove(p + 4 - pstClient->m_stRecvBuf.GetUsedBuf());
            }

            int iQueueIndex = -1;
            const char* pID = strstr(pstClient->m_stRecvBuf.GetUsedBuf(), "serverid");
            if (pID != NULL)
            {
                const char* pNum = strstr(pID, "\r\n\r\n");
                if (pNum != NULL && pNum - pID > 0)
                {
                    CTKeyValue stKeyVal;
                    stKeyVal.ParseFromHttpParam(pID, pNum - pID);
                    int iIntTmp = CTStringUtils::StrToInt<int>(stKeyVal.GetValue("serverid"));
                    if (iIntTmp > 0)
                    {
                        iQueueIndex = CONF->GetIndexByWebID(iIntTmp);
                        if (iQueueIndex >= 0)
                        {
                            pstClient->SetShmQueueIndex(iQueueIndex);
                            CT_TRACE(("TGW:Client(%u) Chg Shm Queue Index(%d)", pstClient->m_uiSeq, iQueueIndex));
                        }
                    }
                }
            }

            if (iQueueIndex < 0)
            {
                CT_ERROR(("TGW:Client(%u) %s", pstClient->m_uiSeq, pstClient->m_stRecvBuf.GetUsedBuf()));
            }

            iMsgLen = 0;
            pstClient->m_stRecvBuf.Clear();//整个包丢弃

            return 0;
        }

		int iPackageLen = ntohl(*(int*)(pstClient->m_stRecvBuf.GetUsedBuf()));
		if (iPackageLen <= pstClient->m_stRecvBuf.GetUsedLen())
		{
			iLen = iPackageLen;
            pszMsgBuf = pstClient->m_stRecvBuf.GetUsedBuf() + sizeof(int);
            iMsgLen = iLen - sizeof(int);
            if (iMsgLen <= 0)
            {
                CT_WARNING(("Invalid package length (%d) and message length (%d)",
                    iLen, iMsgLen));
                return -2;
            }

            //检查结尾
            char p = *(char*)(pstClient->m_stRecvBuf.GetUsedBuf() + iLen - 1);
            if (p != '\t')
            {
                CT_ERROR(("Invalid package content (len=%d) flag error (%d)", iLen, p));
                return -2;
            }
		}
        else  //消息没收完
        {
            iMsgLen = 0;
            return 0;
        }

		if (iMsgLen <= 0)
		{
			return -1;
		}

        return 0;
	}
	else if (pstClient->m_pstListern->m_stListenInfo.m_stPackageType == enp_package_string)
	{
		char* p = strchr(pstClient->m_stRecvBuf.GetUsedBuf(), '\n');
		if (p)
		{
			iLen = (int) (p - pstClient->m_stRecvBuf.GetUsedBuf()) + 1;
            pszMsgBuf = pstClient->m_stRecvBuf.GetUsedBuf();
            iMsgLen = iLen;
		}
		else if (pstClient->m_stRecvBuf.GetFreeLen() <= 0)
		{
			//这个包还没有结束，然而clienthandle的recvbuff已经满了，
			//这一定是受到了攻击。返回-2,上层函数关闭这个链接。
			CT_ERROR(("Got a invalid package on ip %u",
				pstClient->m_stNetHead.uiRemoteIP));
			return -2;
		}

        return 0;
	}
	else if (pstClient->m_pstListern->m_stListenInfo.m_stPackageType == enp_package_binary)
	{
        if (pstClient->m_stRecvBuf.GetUsedLen() < (int)sizeof(int))
        {
            iMsgLen = 0;
            return 0;
        }

		int iPackageLen = ntohl(*(int*)(pstClient->m_stRecvBuf.GetUsedBuf()));
		if (iPackageLen <= pstClient->m_stRecvBuf.GetUsedLen())
		{
			iLen = iPackageLen;
            pszMsgBuf = pstClient->m_stRecvBuf.GetUsedBuf() + sizeof(int);
            iMsgLen = iLen - sizeof(int);
            if (iMsgLen <= 0)
            {
                CT_WARNING(("Invalid package length (%d) and message length (%d)",
                    iLen, iMsgLen));
                return -2;
            }
		}

		if (iMsgLen <= 0)
		{
			return -1;
		}

        return 0;
	}
    else if (pstClient->m_pstListern->m_stListenInfo.m_stPackageType == enp_package_flash)
    {
        if (pstClient->m_stRecvBuf.GetUsedLen() < (int)sizeof(int))
        {
            iMsgLen = 0;
            return 0;
        }

        if (IsPolicyString(pstClient))
        {
            iMsgLen = FLASH_POLICY_STRING_LEN + 1;
            iLen = FLASH_POLICY_STRING_LEN + 1;
            pszMsgBuf = pstClient->m_stRecvBuf.GetUsedBuf();
            return 0;
        }

        iLen = ntohl(*(int*)(pstClient->m_stRecvBuf.GetUsedBuf()));
        if (iLen > pstClient->m_stRecvBuf.GetUsedLen()) //收到半个包或者包太大，包太大由外层判断
        {
            return 0;
        }

        iMsgLen = iLen - sizeof(int);
        pszMsgBuf = pstClient->m_stRecvBuf.GetUsedBuf() + sizeof(int);

        /*
        char* p = strchr(pstClient->m_stRecvBuf.GetUsedBuf(), '\0');
        if (p)
        {
            iLen = (int) (p - pstClient->m_stRecvBuf.GetUsedBuf()) + 1;
            if (iLen > pstClient->m_stRecvBuf.GetUsedLen())
            {
                iLen = pstClient->m_stRecvBuf.GetUsedLen();
            }

            pszMsgBuf = pstClient->m_stRecvBuf.GetUsedBuf();
            iMsgLen = iLen;
        }
        */

        return 0;
    }
    else if (pstClient->m_pstListern->m_stListenInfo.m_stPackageType == enp_package_encrypted)
    {
        if (pstClient->m_stRecvBuf.GetUsedLen() < (int)sizeof(int))
        {
            iMsgLen = 0;
            return 0;
        }

        if (IsPolicyString(pstClient))
        {
            iMsgLen = FLASH_POLICY_STRING_LEN + 1;
            iLen = FLASH_POLICY_STRING_LEN + 1;
            pszMsgBuf = pstClient->m_stRecvBuf.GetUsedBuf();
            return 0;
        }

        int iPackageLen = ntohl(*(int*)(pstClient->m_stRecvBuf.GetUsedBuf()));
        if (iPackageLen <= pstClient->m_stRecvBuf.GetUsedLen())
        {
            iLen = iPackageLen;
            pszMsgBuf = pstClient->m_stRecvBuf.GetUsedBuf() + sizeof(int);
            iMsgLen = iLen - sizeof(int);
            if (iMsgLen <= 0)
            {
                CT_WARNING(("Invalid package length (%d) and message length (%d)",
                    iLen, iMsgLen));
                return -2;
            }
        }

        if (iMsgLen <= 0)
        {
            return -1;
        }

        return 0;
    }

	return -1;
}

bool CEnpCtrl::FromAdmin(const CEnpNetHead& stHead)
{
    return (stHead.uiLocalIP == inet_addr(CONF->AdminHost.Get()) &&
        (stHead.unLocalPort == CONF->AdminPort));
}

void CEnpCtrl::DumpNetHead(CEnpNetHead& stHead)
{
	CT_TRACE(("%s", "---- BeginDumpNetHead ----"));
	struct in_addr in;
	in.s_addr = stHead.uiRemoteIP;
	CT_TRACE(("%-16s = %s", "RemoteIP", inet_ntoa(in)));
	CT_TRACE(("%-16s = %u", "RemotePort", stHead.unRemotePort));
	CT_TRACE(("%-16s = %u", "Handle", stHead.uiHandle));
	CT_TRACE(("%-16s = %u", "HandleSeq", stHead.uiHandleSeq));
	CT_TRACE(("%-16s = %u", "CreateTime", stHead.uiCreateTime));
	CT_TRACE(("%-16s = %u", "LastTime", stHead.uiLastTime));
	CT_TRACE(("%-16s = %u", "Reserve1", stHead.uiAct1));
	CT_TRACE(("%-16s = %u", "Reserve2", stHead.uiAct2));
	CT_TRACE(("%-16s = %u", "LiveFlag", stHead.unLiveFlag));
	CT_TRACE(("%-16s = %u", "DataLength", stHead.unDataLength));
	CT_TRACE(("%s", "---- EndDumpNetHead ----"));
}

//===============================================
int CEnpCtrl::AllocRecvBuffer(CEnpClient* pstClient)
{
    if (pstClient->m_stRecvBuf.IsAttached())
    {
        return 0;
    }

    int iIndex = m_stRecvBufMgr.InfoListAlloc(BUFF_INDEX, USED_LIST);
    if (iIndex < 0)
    {
        return iIndex;
    }

    return pstClient->m_stRecvBuf.Attach(m_stRecvBufMgr[iIndex],
        m_stRecvBufMgr.GetObjectSize(), iIndex);
}

int CEnpCtrl::AllocSendBuffer(CEnpClient* pstClient)
{
    if (pstClient->m_stSendBuf.IsAttached())
    {
        return 0;
    }

    int iIndex = m_stSendBufMgr.InfoListAlloc(BUFF_INDEX, USED_LIST);
    if (iIndex < 0)
    {
        return iIndex;
    }

    return pstClient->m_stSendBuf.Attach(m_stSendBufMgr[iIndex],
        m_stSendBufMgr.GetObjectSize(), iIndex);
}

int CEnpCtrl::FreeRecvBuffer(CEnpClient* pstClient)
{
    if (!pstClient->m_stRecvBuf.IsAttached())
    {
        return 0;
    }

    m_stRecvBufMgr.InfoListMove(pstClient->m_stRecvBuf.Act(),
        BUFF_INDEX, FREE_LIST);

    pstClient->m_stRecvBuf.Detach();
    return 0;
}

int CEnpCtrl::FreeSendBuffer(CEnpClient* pstClient)
{
    if (!pstClient->m_stSendBuf.IsAttached())
    {
        return 0;
    }

    m_stSendBufMgr.InfoListMove(pstClient->m_stSendBuf.Act(),
        BUFF_INDEX, FREE_LIST);

    pstClient->m_stSendBuf.Detach();
    return 0;
}

int CEnpCtrl::RecvSocket(CEnpClient* pstClient)
{
    int iRet = 0;
    int iIndex = m_stClientFactory.CalcObjectPos(pstClient);

	if(m_stClientFactory.IsFree(pstClient))
	{
		CT_WARNING(("client is invalid"));
		return 0;
	}

    iRet = AllocRecvBuffer(pstClient);
    if (iRet)
    {
        CT_FATAL(("handle(%d) alloc recv buffer failed ret=%d", iIndex, iRet));
        return -1;
    }

    pstClient->m_stNetHead.uiLastTime = m_uiNow;
    if (pstClient->m_stRecvBuf.GetFreeLen() <= 0)
    {
        CT_WARNING(("handle(%d) recv buffer no space to recv", iIndex));
        return AfterRecvSocket(pstClient);
    }

    int iRecvLen = 0;
    iRet = pstClient->m_stSocket.Recv(pstClient->m_stRecvBuf.GetFreeBuf(),
        pstClient->m_stRecvBuf.GetFreeLen(), iRecvLen);

    if (iRecvLen > 0)
    {
        pstClient->m_stRecvBuf.Append(iRecvLen);
    }

	CT_TRACE(("recv len = %d, ret = %d", iRecvLen, iRet));

    if (iRet)
    {
        if (iRet == CT_ECONNRESET) // 远程连接已关闭
        {
            AfterRecvSocket(pstClient);  //可能会有notify信息
            return CloseSocket(pstClient, enp_flag_remoteclose);
        }
        else if (iRet == CT_EWOULDBLOCK || iRet == CT_EINPROGRESS)
        {
            return AfterRecvSocket(pstClient);
        }
        else
        {
            CT_ERROR(("handle(%d) recv failed %d", iIndex, iRet));
            CloseSocket(pstClient, enp_flag_error);
            return -1;
        }
    }

    return AfterRecvSocket(pstClient);
}

int CEnpCtrl::SendSocket(CEnpClient* pstClient)
{
    if (!pstClient->m_stSendBuf.IsAttached())
    {
        return 0;
    }

	if (pstClient->m_stSendBuf.GetUsedLen() <= 0)
    {
        CT_TRACE(("no data to send"));
        FreeSendBuffer(pstClient);
		return 0;
    }

	pstClient->m_stNetHead.uiLastTime = m_uiNow;

    int iRet = 0;
    int iIndex = m_stClientFactory.CalcObjectPos(pstClient);
    int iSendLen = 0;

    // 根据listen端口的属性来发送消息完整性标识
    // protobuf类型就是先发4字节的长度并保证最后以\t结尾
    // binary类型就是先发4 字节的长度
    // string类型就是保证最后以\n结尾
    // flash类型就是保证最后以\0结尾
    if (pstClient->m_pstListern->m_stListenInfo.m_stPackageType == enp_package_http)
    {
        /*
        if (pstClient->m_stSendBuf.GetFreeLen() < 4)
        {
            CT_TRACE(("handle(%d) want to send http msg, need add end, but no free space", iIndex));
            CloseSocket(pstClient, enp_flag_error);
            return -1;
        }

        pstClient->m_stSendBuf.Append("\r\n\r\n", 4);
        */

        pstClient->m_stNetHead.unLiveFlag |= enp_flag_askclose;  //发送后关闭链接
    }
    else if (pstClient->m_pstListern->m_stListenInfo.m_stPackageType == enp_package_protobuf)
    {
        if (pstClient->m_stSendBuf.GetUsedBuf()[pstClient->m_stSendBuf.GetUsedLen() - 1] != '\t')
        {
            if (pstClient->m_stSendBuf.GetFreeLen() == 0)
            {
                CT_TRACE(("handle(%d) want to send string msg, need add \\t, but no free space", iIndex));
                CloseSocket(pstClient, enp_flag_error);
                return -1;
            }

            pstClient->m_stSendBuf.Append("\t", 1);
        }
    }
	else if (pstClient->m_pstListern->m_stListenInfo.m_stPackageType == enp_package_binary)
	{
		;
	}
    else if (pstClient->m_pstListern->m_stListenInfo.m_stPackageType == enp_package_string)
    {
        if (pstClient->m_stSendBuf.GetUsedBuf()[pstClient->m_stSendBuf.GetUsedLen() - 1] != '\n')
        {
            if (pstClient->m_stSendBuf.GetFreeLen() == 0)
            {
                CT_TRACE(("handle(%d) want to send string msg, need add \\n, but no free space", iIndex));
                CloseSocket(pstClient, enp_flag_error);
                return -1;
            }

            pstClient->m_stSendBuf.Append("\n", 1);
        }
    }
    else if (pstClient->m_pstListern->m_stListenInfo.m_stPackageType == enp_package_flash)
    {
        if (pstClient->m_stSendBuf.GetUsedBuf()[pstClient->m_stSendBuf.GetUsedLen() - 1] != '\0')
        {
            if (pstClient->m_stSendBuf.GetFreeLen() == 0)
            {
                CT_TRACE(("handle(%d) want to send flash msg, need add \\n, but no free space", iIndex));
                CloseSocket(pstClient, enp_flag_error);
                return -1;
            }

            pstClient->m_stSendBuf.Append("\0", 1);
        }
    }

    if (pstClient->m_pstListern->m_stListenInfo.m_stPackageType == enp_package_http)
    {
        CT_TRACE(("send: %s", pstClient->m_stSendBuf.GetUsedBuf()));
    }

    iRet = pstClient->m_stSocket.SendEx(pstClient->m_stSendBuf.GetUsedBuf(),
        pstClient->m_stSendBuf.GetUsedLen(), iSendLen);
    if (iRet && !(iRet == CT_EWOULDBLOCK || iRet == CT_EINPROGRESS))
    {
		// 发送失败
		if (CT_ECONNRESET == iRet || EPIPE == iRet)
		{
			CT_WARNING(("handle(%d) write msg size failed, client disconnected", iIndex));
		}
		else
		{
			CT_ERROR(("handle(%d) write failed socket=%d err=%d",
				iIndex, pstClient->m_stSocket.GetSocket(), iRet));
		}
        CloseSocket(pstClient, enp_flag_error);
        return iRet;
    }

    if (iSendLen == 0)
    {
        // 可能系统的发送缓冲区已满, 那就先缓存一下, 稍后发送
        CT_WARNING(("handle(%d) send 0 bytes", iIndex));
        return 0;
    }

    pstClient->m_iSendBytes += iSendLen;
    pstClient->m_stSendBuf.Remove(iSendLen);
    return AfterSendSocket(pstClient);
}

int CEnpCtrl::CloseSocket(CEnpClient* pstClient, unsigned short unLiveFlag)
{
	CT_TRACE(("handle %d close and clear, liveflag=%hu, has %d bytes not send to client",
        m_stClientFactory.CalcObjectPos(pstClient), unLiveFlag,
        pstClient->m_stSendBuf.GetUsedLen()));

    // 满足3个条件才通知上层
    // 1.socket有效
    // 2.不是enpsvr主动关闭的
    // 3.连接建立后向上层成功发过数据
    if (pstClient->m_stSocket.IsValid() && !(unLiveFlag & enp_flag_askclose) &&
        pstClient->m_iRecvBytes > 0)
    {
        PutOneNotify(pstClient, unLiveFlag);
    }

    FreeRecvBuffer(pstClient);
    FreeSendBuffer(pstClient);
	m_stClientFactory.Free(pstClient);

    //记录连接关闭
    m_stFlowCtrl.ClientDisconnect();
    return 0;
}

void CEnpCtrl::DumpHandleInfo(CEnpClient* pstClient)
{
	CT_TRACE(("%s", "---- BeginDumpHandleInfo ----"));
	CT_TRACE(("%-16s = %u", "Handle", m_stClientFactory.CalcObjectPos(pstClient)));
	struct in_addr in;
	in.s_addr = pstClient->m_stNetHead.uiRemoteIP;
	CT_TRACE(("%-16s = %s", "RemoteIP", inet_ntoa(in)));
	CT_TRACE(("%-16s = %u", "RemotePort", pstClient->m_stNetHead.unRemotePort));
	CT_TRACE(("%-16s = %u", "Socket", pstClient->m_stSocket.GetSocket()));
	CT_TRACE(("%-16s = %u", "HandleSeq", pstClient->m_stNetHead.uiHandleSeq));
	CT_TRACE(("%-16s = %u", "CreateTime", pstClient->m_stNetHead.uiCreateTime));
	CT_TRACE(("%-16s = %u", "LastTime", pstClient->m_stNetHead.uiLastTime));
	CT_TRACE(("%-16s = %u", "Act1", pstClient->m_stNetHead.uiAct1));
	CT_TRACE(("%-16s = %u", "Act2", pstClient->m_stNetHead.uiAct2));
	CT_TRACE(("%-16s = %u", "LiveFlag", pstClient->m_stNetHead.unLiveFlag));
	CT_TRACE(("%-16s = %u", "RecvBufAct", pstClient->m_stRecvBuf.Act()));
	CT_TRACE(("%-16s = %u", "RecvBufLen", pstClient->m_stRecvBuf.GetUsedLen()));
	CT_TRACE(("%-16s = %u", "SendBufAct", pstClient->m_stSendBuf.Act()));
	CT_TRACE(("%-16s = %u", "SendBufLen", pstClient->m_stSendBuf.GetUsedLen()));
	CT_TRACE(("%s", "---- EndDumpHandleInfo ----"));
}

void CEnpCtrl::DumpStatInfo()
{
    m_stat.Dump(CT_STAT);

	CT_STAT->Log(EInfo, "Handle: All=%d Used=%d Free=%d Remain=%d",
        m_stClientFactory.GetObjectCount(),
		m_stClientFactory.Size(USED_LIST, ALLOC_INDEX),
		m_stClientFactory.Size(FREE_LIST, ALLOC_INDEX),
        m_stClientFactory.Size(REMAIN_LIST, REMAIN_INDEX));

    CT_STAT->Log(EInfo, "RecvBuffer: All=%d Used=%d Free=%d",
        m_stRecvBufMgr.GetObjectCount(),
		m_stRecvBufMgr.Size(USED_LIST),
		m_stRecvBufMgr.Size(FREE_LIST));

    CT_STAT->Log(EInfo, "SendBuffer: All=%d Used=%d Free=%d",
        m_stSendBufMgr.GetObjectCount(),
        m_stSendBufMgr.Size(USED_LIST),
        m_stSendBufMgr.Size(FREE_LIST));

    CT_STAT->Log(EInfo, "FlowCtrl: %s\n", m_stFlowCtrl.GetStat());
}

bool CEnpCtrl::IsPolicyString(CEnpClient* pstClient)
{
    return ( (pstClient->m_pstListern->m_stListenInfo.m_stPackageType == enp_package_flash || pstClient->m_pstListern->m_stListenInfo.m_stPackageType == enp_package_protobuf)
        && strncmp(pstClient->m_stRecvBuf.GetUsedBuf(), FLASH_POLICY_STRING, FLASH_POLICY_STRING_LEN) == 0);
}

int CEnpCtrl::CheckPolicyString(CEnpClient* pstClient)
{
    int iRet = 0;

    // 先释放RecvBuf
    iRet = FreeRecvBuffer(pstClient);
    if (iRet)
    {
        CT_WARNING(("FreeRecvBuffer failed %d", iRet));
    }

    // 发送策略文件
    iRet = AllocSendBuffer(pstClient);
    if (iRet)
    {
        CT_FATAL(("AllocSendBuffer failed %d", iRet));
        return -1;
    }

    pstClient->m_stSendBuf.Append(
        pstClient->m_pstListern->m_stListenInfo.m_stBufferofPolicy.GetUsedBuf(),
        pstClient->m_pstListern->m_stListenInfo.m_stBufferofPolicy.GetUsedLen());

    if (pstClient->m_stSendBuf.GetUsedLen() == 0)
    {
        CT_TRACE(("no data to send"));
        return -1;
    }

    iRet = SendSocket(pstClient);
    if (iRet)
    {
        CT_ERROR(("Send data failed %d", iRet));
        return -1;
    }

    return 0;
}

